package com.hupu.jrs.widget

import android.content.Context
import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Path
import android.graphics.Rect
import android.text.TextUtils
import android.util.AttributeSet
import android.view.View
import com.hupu.jrs.R
import com.yalantis.phoenix.util.Logger

class LabelViewHelper(private val context: Context, attrs: AttributeSet, defStyleAttr: Int) {

    private var distance: Int = 0
    private var height: Int = 0
    var labelText: String? = null
        private set
    var labelBackgroundColor: Int = 0
        private set
    private var textSize: Int = 0
    var labelTextColor: Int = 0
        private set
    var isLabelVisual: Boolean = false
        private set
    var labelOrientation: Int = 0
        private set

    private var startPosX: Float = 0.toFloat()
    private var startPosY: Float = 0.toFloat()
    private var endPosX: Float = 0.toFloat()
    private var endPosY: Float = 0.toFloat()

    private val rectPaint: Paint
    // simulator
    private val rectPath: Path
    private val textPaint: Paint
    private val textBound: Rect

    val labelHeight: Int
        get() = px2Dip(this.height.toFloat())

    val labelDistance: Int
        get() = px2Dip(this.distance.toFloat())

    val labelTextSize: Int
        get() = px2Dip(this.textSize.toFloat())

    init {

        val attributes = context.obtainStyledAttributes(attrs, R.styleable.LabelView, defStyleAttr, 0)
        distance = attributes.getDimensionPixelSize(R.styleable.LabelView_label_distance,
                dip2Px(DEFAULT_DISTANCE.toFloat()))
        height = attributes.getDimensionPixelSize(R.styleable.LabelView_label_height,
                dip2Px(DEFAULT_HEIGHT.toFloat()))
        labelText = attributes.getString(R.styleable.LabelView_label_text)
        labelBackgroundColor = attributes.getColor(R.styleable.LabelView_label_backgroundColor, DEFAULT_BACKGROUND_COLOR)
        textSize = attributes.getDimensionPixelSize(R.styleable.LabelView_label_textSize,
                dip2Px(DEFAULT_TEXT_SIZE.toFloat()))
        labelTextColor = attributes.getColor(R.styleable.LabelView_label_textColor, DEFAULT_TEXT_COLOR)
        isLabelVisual = attributes.getBoolean(R.styleable.LabelView_label_visual, false)
        labelOrientation = attributes.getInteger(R.styleable.LabelView_label_orientation, DEFAULT_ORIENTATION)
        attributes.recycle()

        rectPaint = Paint()
        rectPaint.isDither = true
        rectPaint.isAntiAlias = true
        rectPaint.style = Paint.Style.STROKE
        rectPaint.strokeJoin = Paint.Join.ROUND
        rectPaint.strokeCap = Paint.Cap.SQUARE

        rectPath = Path()
        rectPath.reset()

        textPaint = Paint()
        textPaint.isDither = true
        textPaint.isAntiAlias = true
        textPaint.strokeJoin = Paint.Join.ROUND
        textPaint.strokeCap = Paint.Cap.SQUARE

        textBound = Rect()
    }

    fun onDraw(canvas: Canvas, measuredWidth: Int, measuredHeight: Int) {
        if (!isLabelVisual) {
            return
        }

        val actualDistance = (distance + height / 2).toFloat()
        calcOffset(actualDistance, measuredWidth, measuredHeight)

        rectPaint.color = labelBackgroundColor
        rectPaint.strokeWidth = height.toFloat()

        rectPath.reset()
        rectPath.moveTo(startPosX, startPosY)
        rectPath.lineTo(endPosX, endPosY)
        canvas.drawPath(rectPath, rectPaint)

        textPaint.textSize = textSize.toFloat()
        textPaint.color = labelTextColor
        textPaint.getTextBounds(labelText, 0, labelText!!.length, textBound)

        canvas.drawTextOnPath(labelText!!, rectPath, 1.4142135f * actualDistance / 2 - textBound.width() / 2,
                (textBound.height() / 2).toFloat(), textPaint)
    }

    private fun calcOffset(actualDistance: Float, measuredWidth: Int, measuredHeight: Int) {
        when (labelOrientation) {
            1 -> {
                startPosX = 0f
                startPosY = actualDistance
                endPosX = actualDistance
                endPosY = 0f
            }
            2 -> {
                startPosX = measuredWidth - actualDistance
                startPosY = 0f
                endPosX = measuredWidth.toFloat()
                endPosY = actualDistance
            }
            3 -> {
                startPosX = 0f
                startPosY = measuredHeight - actualDistance
                endPosX = actualDistance
                endPosY = measuredHeight.toFloat()
            }
            4 -> {
                startPosX = measuredWidth - actualDistance
                startPosY = measuredHeight.toFloat()
                endPosX = measuredWidth.toFloat()
                endPosY = measuredHeight - actualDistance
            }
        }
    }

    private fun dip2Px(dip: Float): Int {
        return (dip * context.resources.displayMetrics.density + 0.5f).toInt()
    }

    private fun px2Dip(px: Float): Int {
        return (px / context.resources.displayMetrics.density + 0.5f).toInt()
    }

    fun setLabelHeight(view: View, height: Int) {
        if (this.height != dip2Px(height.toFloat())) {
            this.height = dip2Px(height.toFloat())
            view.invalidate()
        }
    }

    fun setLabelDistance(view: View, distance: Int) {
        if (this.distance != dip2Px(distance.toFloat())) {
            this.distance = dip2Px(distance.toFloat())
            view.invalidate()
        }
    }

    fun setLabelVisual(view: View, visual: Boolean) {
        if (this.isLabelVisual != visual) {
            this.isLabelVisual = visual
            view.invalidate()
        }
    }

    fun setLabelOrientation(view: View, orientation: Int) {
        if (this.labelOrientation != orientation && orientation <= 4 && orientation >= 1) {
            this.labelOrientation = orientation
            view.invalidate()
        }
    }

    fun setLabelTextColor(view: View, textColor: Int) {
        if (this.labelTextColor != textColor) {
            this.labelTextColor = textColor
            view.invalidate()
        }
    }

    fun setLabelBackgroundColor(view: View, backgroundColor: Int) {
        if (this.labelBackgroundColor != backgroundColor) {
            this.labelBackgroundColor = backgroundColor
            view.invalidate()
        }
    }

    fun setLabelText(view: View, text: String) {
        if (!TextUtils.equals(this.labelText, text)) {
            this.labelText = text
            Logger.d("setLabelText:" + text)
            view.invalidate()
        }
    }

    fun setLabelTextSize(view: View, textSize: Int) {
        if (this.textSize != textSize) {
            this.textSize = textSize
            view.invalidate()
        }
    }

    companion object {

        private val LEFT_TOP = 1
        private val RIGHT_TOP = 2
        private val LEFT_BOTTOM = 3
        private val RIGHT_BOTTOM = 4

        private val DEFAULT_DISTANCE = 20
        private val DEFAULT_HEIGHT = 20
        private val DEFAULT_TEXT_SIZE = 14
        private val DEFAULT_BACKGROUND_COLOR = -0x12faf3
        private val DEFAULT_TEXT_COLOR = -0x1
        private val DEFAULT_ORIENTATION = RIGHT_TOP
    }
}